california

Introduction

Our goal for this project was to create interesting visualization showing correlations between causes of death and the demographic trends in the zip codes of California.

In order to do so we are cleaning dirty Zip code data from the US Census as well as zip code data corresponding to cause of death. These data sets are available on data.world and were joined using Tableau and R, which we used to produce the visualizations we present in this document.

The following links refer to the census data used for out visualizations.

Median Income data was taken from the following link to the US Census Data in data.world: https://data.world/uscensusbureau/acs-2015-5-e-income

Median Age data was taken from the following link to the US Census Data in data.world: https://data.world/uscensusbureau/acs-2015-5-e-agesex

Dominant Race data was taken from the following link to the US Census Data in data.world: https://data.world/uscensusbureau/acs-2015-5-e-race

R Configuration

Below we display our sessionInfo().

sessionInfo(package=NULL)
## R version 3.3.3 (2017-03-06)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 14393)
## 
## locale:
## [1] LC_COLLATE=English_United States.1252 
## [2] LC_CTYPE=English_United States.1252   
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## loaded via a namespace (and not attached):
##  [1] backports_1.0.5 magrittr_1.5    rprojroot_1.2   tools_3.3.3    
##  [5] htmltools_0.3.5 yaml_2.1.14     Rcpp_0.12.10    stringi_1.1.5  
##  [9] rmarkdown_1.5   knitr_1.15.1    stringr_1.2.0   digest_0.6.12  
## [13] evaluate_0.10

Data Summary

The following heads and summaries demonstrate the data that will be joining via data.world in our queries when using shiny. This data will also be joined in tableau for the corresponding visualizations.

Processing the Data

The csv files containing our data of interest were passed through individual ETL files for cleaning. In this process spaces are included between upper and lower cased letters and ampersands are changed to the word “and”.These subtleties among others are done to effectively upload the data files to data.world. Because our data did not require much “cleaning” or renaming of columns, we did not need to include in depth code in the ETL file. We used many “cookie-cutter” ETL files to clean the many files we used for our joins. These files include “ETL_median_age.R, ETL_dominant_race.R, ETL_median_income.R” Below is a source or link to one of our ETL files.

Below is a source of our etl file used to clean our dominant race file,

## Loading required package: readr
## Loading required package: plyr
## Parsed with column specification:
## cols(
##   ZipCode = col_integer(),
##   Dominant = col_character()
## )
## # A tibble: 6 × 2
##   ZipCode Dominant
##     <int>    <chr>
## 1    1001    White
## 2    1002    White
## 3    1013    White
## 4    1258    White
## 5    4348    White
## 6   31532    White
## # A tibble: 6 × 2
##   ZipCode Dominant
##    <fctr>   <fctr>
## 1    1001    White
## 2    1002    White
## 3    1013    White
## 4    1258    White
## 5    4348    White
## 6   31532    White

The following screen shot shows some of the code used to clean the dominant race file.

knitr::include_graphics("../01Data/dominantRace.png")

Tableau Visualizations Steps

Step 1 - Retrieving our Data

We pulled in 2 grouped data sets from our project that originated from the US Census (Median_Income_Raw.csv, and Median_Age_Raw.csv). In addition, we grouped a set from race deomgraphics Census data to create the domianat_race.csv. In order to create this file, we queried the orginal census data in a way we could define the domianant race in each zip code (sql commands at the bottom of the presentation).A new column was added to the data set indicating the most represented race in each zip code. We used the data.world connector to retrieve everything from our final project site on data.world. This is where we also pulled the Cause of Death data set. Finally we pulled in a data file that contained California zipcodes, cause of death, and the count of each type that fell in that category. These files were inner joined on ZIP Code to analyze cause and count of death to median income, dominant race, and median age in each ZIP Code.

Boxplot Visualization Steps

Step 1 - Boxplot Overview

In order to create our box plot we set causes of deaths as the columns which can be seen along the x-axis of the plot. The row are set as the count of deaths as seen on the y-axis of the plot. Each zip code has a corresponding point on the boxplot for each cause of death. We set dominant race as the color of the points in the plot. Therefore, the color of each point depends on each zip code’s dominant race. The boxes along each column mark the 25th to 75th percentile of counts of deaths per zip code for each cause. The whiskers mark the highest and lowest count values considered to not be outliers.

Step 2 - Filter

We added a filter to this boxplot in order to define the range of the median incomes of the zipcodes displyed.

This observation seems relatively odd. If even just looking at the general death rate we see that it starts high, goes down, then goes back up again as income is steadily increasing. If you are only operating under the premise that more income means better healthcare/lifestyle which means greater longevity this seems counter intuitive. However if you consider who is making the higher income amounts it makes more sense.

income

Histogram Visualization Steps

##Scatter Plot Visualization Steps

Crosstab Visualization Steps

Step 1 - Table Caculations

The two table calculation pills we included in our Tableau file were “Calculated Diff from Avg” and “Calculated Weighted Diff from Avg.” Reference lines were also included in our project. This can be seen in the “Race Table Calculations” visualization. In this case, reference lines were used to depict an average count of death by race for each cause of death.

Barchart Visualization Steps

Step 1 - Retrieving our Data

We pulled in 3 data sets from our project that originated from the US Census (median_income.csv, median_age.csv, and dominant_race.csv).We found that some columns in these data sets had to be grouped, so we included our SQL code at the bottom of the project that describes how we created bins for ages, incomes, and dominant races.For this same reason, we did not pull from the Census Bureau’s data. Instead, we used the data.world connector to retrieve everything from our project 6 site on data.world. This is where we also pulled the Cause of Death data set. These files were inner joined on ZIP Code to analyze cause and count of death to median income, dominant race, and median age in each ZIP Code.

Step 2 - Barchart Overview

We created barcharts between either median income, dominant race, or median age (one blue) and cause of death (second blue) in the row slot. This then lists all the causes of death and within each cause of death lists a row for either median age, or dominant race. A sum of the count of deaths (green) was added as the column of the barcharts. With this count we can compare the number of people dying of a certain cause of death across zip codes of different median ages (for example). Nonetheless, we considered that certain races, and ages were over represented in our data. Therefore, we created a calculated field to add to our column slot named Weighted Race/Age Deaths which will be described in the following bullet. This calculated field allows us to recognize which populations are more likely to die of certain causes than predicting from a raw count of deaths.

Step 3 - Calculated Fields

Furthermore, as mentioned previously we created three calculated field producing a Weighted count of Deaths for income, age, and dominant race. To illustrate the process we can take the deaths by race barchart as an example. The calculated field takes the count of deaths in a zip code dominanted by a certain race due to a certain cause and divides it by the total count of deaths in zip codes with that dominant race (regardless of cause of death). This calculated field creates a proportion of deaths due to certain causes that accounts for overrepresented races. We can then compare weighted proportions to more accurately predict which zip codes are more likely to have deaths of a certain cause with respect to their dominant race. This same process was followed for median income, and median age. These weighted count of death was added to the columns lot of our barcharts to create a separate barchart next to raw death count columns. The rows were maintained the same and columns were added to represent the weighted count of deaths.

Barchart Visualization Steps

Reference Lines

We decided to use an average reference line for all our barcharts. This takes the average death count between different race dominanted zip codes (for eaxmple) for a certain cause of death and creates a representative line along our columns to visualize the average count. In addition, this average line was created for our weighted death count. The average weighted death count across different race dominanted zip codes (for example) was displayed for each cuase of death as a line acorss our columns.

As shown below, reference lines were implemented in the “Age Reference Lines” visualization to depict the the average count of deaths by age group for each cause of death. 95% confidence intervals were also displayed on this visualization to show the reader that the true count of deaths within the actual age groups would fall within the purple highlighted range 95% of the time. #####Formatting

Formatting is depicted in our Income ID Sets Bar chart. Because our y-axis units are Income, they are formatted as Currency. All of these items are depicted in the visualizations below.

ID Sets

In order to use ID sets we defined ‘at risk income brackets’. This was done by creating a bar graph listing different median incomes as bins and creating columns with weighted death counts for zipcodes of each median income (irrespective of cause of death). Zipcodes of median incomes with more than seven weighted death counts were categorized as ‘at risk’. This is then taken to create another bar graph with causes of death listed as the bins and weighted count of death as the parameter of the height of the bars. By applying our ‘at risk’ ID Set we divide the bars in to a proportion at risk and a proportion out of risk. Therefore, for each cause of death we can recognize the amount of weighted deaths in zip codes with a weighted count of deaths above the thershold of seven weighted deaths.

Tableau Visualizations

Visualization Type 1 - BarGraphs

The following visualizations were created to give an understanding of how our weighted death counts was created and what our calculted field represents.

Visualization Type 2 - Bar Charts

The following barcharts were created with the process descibed in the Tableau visualization steps.

Dominant Race Barchart

Looking at the tables on the left, which show the unweighted death counts, one would think white people are more likely to die from just about everything. However, this is simply because there are more whites than any other race in the population, meaning they have more deaths. In order to account for this, we instead visualized race and cause of death using weighted race deaths (see “Created Weighed Race Deaths” tab). This easily allows us to compare how likely different races are to die of a given cause of death. Our interesting findings is that of the three highest causes of deaths: cancer, heart disease, and “other”, blacks are, on average, more likely to die than any other race, taking into account their numbers in the total population.

Median Age Barchart

Looking at the tables on the left, which show the unweighted death counts, one would think people who make between 30 and 40 thousand dollars per year are more likely to die from just about everything. However, this is simply because there are more people in that income range than any other in the population, meaning they have more deaths. In order to account for this, we instead visualized race and cause of death using weighted income deaths (see “Created Weighed Income Deaths” tab). This easily allows us to compare how likely people in different income ranges are to die of a given cause of death Our interesting finding is that heart disease and cancer are the most likely cause of death across all age groups. For cancer we can notice that a larger proportion of people in age groups below 50 years are dying of cancer compared to people in age groups of 60 and above.

Visualization 3 - ID Sets - Income ID - In, Out

The visualization below uses Sets to depict income brackets that are either “at-risk”" or not “at-risk.” In this case, “at-risk” refers to income brakcets that have a weighted death rate of 7 or more. The orange portions of each bar show the amount of deaths within the “at-risk income brackets” set. The grey portions are those out of the set, as their weighted death rate is below 7.

In order to create the set, we selected the income brackets that had a weighted income death rate greater than 7. These were included in the “In” set.

Shiny Visualization Steps

Link: https://anandpant.shinyapps.io/project_final/

The shiny app creates a barchart using causes of death and either median income, median age, or dominant race. This data is brought in from the data.world files which join census data to the causes of death files. This is created with an inner join on the zip code in both files. The SQL to join is found in the server code for our shiny aplication.

The user should click on the get data button. This button sends a SQL query to data.world to join and bring in the data set mentioned above.

The returned data set will be used with ggplot code to create barcharts that show the count of deaths. The rows of the barcharts list the different Causes of Deaths and the different barcharts depict different age groups (for example). Each of the barcharts have a reference line to show the average count of deaths in that age group.

Step 1

Navigate to 02 Shiny and open Server.R

Step 2

Click publish.

Step 3

Click on a tab in the sidebar

Step 4

Select get data. Naviagate to the graph tab. Use the slider to interact.

Shiny Visualizations

Boxplot Tab

Histogram Tab

The histogram displayed is created by grouping zip codes of different median ages to bins with ranges of 5 years. The zip codes corresponding to the median ages assigned by each zip code have their count of deaths summed and displayed as the columns of the plot.

Scatter Plot Tab

The scatter plot created has a point corresponding to the count of deaths of each cause per zip code. These points are organized along the x axis by their median age and placed along the y axis by their count of deaths. The color each point is assigned by the cause of death the count represents. From the plot we can make the observation that median age of zip codes are normally distributed about age. This can be noted by the larger count of deaths in the middle of the plot since most zip codes have middle aged median age zip codes.Less deaths occur in the highest a lowest median age zip codes. The increase in count of deaths around median age of 40 can be explained by the increased risk for heart disease seen in males over the age of 45. High numbers of over 45 year olf males may account for the rise in deaths.

Crosstab Tab

The cross tab created has causes of death labled on the y-axis and dominant race in the x-axis. Each cell then displayed the sum of the count of deaths in the zip codes with a certain dominant race due to a certain cuase. In addition, before retrieving the data, users can define the ranges corresponding to a low, medium, and high KPI using the sliders in the data tab. The KPI we created was average deaths per zip code. This KPI takes the sum of the counts as displayed in the cells and divides that by the number of zip codes taken in to account in the sum of the counts. This definition of high, low and medium average deaths per zip codes is taken by the query sent to data.world. The query returns a column in the data defining whether a cause of death and dominant race combination has a high, low or medium average deaths per zip code. This parameter is then used to color the cells in the crosstab with its corresponding level of average deaths.

Shiny - Median Income Bar Chart

This image shows the barchart created from grouping zip codes by median income.

Bar Chart Tab

For our barchart, median age zip codes were grouped together. These groupings were then each divided by cause of death as seen in the y axis. The length of the bars account for the average death count per zip code for a certain cause of death in zip codes of a certain median age range. In addition a reference line was added to each median age grouping. This line indicates the average of the average deaths per zip codes in each grouping. The numbers labeled next to the bars correspond to the average of the average death count per zip code. From this plot we notice average deaths per zip code due to injury doubles when moving from zip codes from ages 60-70 to zip codes with median ages 70-80.

From the refernce line we can note that the count of deaths by suicide has a tendency to grow closer to the average as median income increases.

Shiny - Dominant Race Bar Chart Finding

This image shows the barchart created from grouping zip codes by dominant race.

From this barchart we find out that only american indian dominated zip codes suffered deaths due to injuries above the average count of deaths due to a cause. All other races had deaths due to injury below the cause death average.

Key for Causes of Death Abbreviations

Cause-of-death were coded using the Tenth Revision of the International Classification of Diseases codes (ICD-10). This is in the same data.world profile (@health) that we retrieved our data for the count of deaths by causes from.

SQL Query for Grouping and Joining data

Dominant Race Query

The following query is an example of how the census data was processed to define the dominant race in a zip code. The same process followed to define median income and median age in each zip code analyzed.

commands
LS0tDQp0aXRsZTogJzxjZW50ZXI+PGI+RmluYWwgUHJvamVjdDogQ2F1c2Ugb2YgRGVhdGggQW5hbHlzaXMgaW4gQ2FsaWZvcm5pYSBaaXAgQ29kZXMNCiAgPC9iPjwvY2VudGVyPicNCmF1dGhvcjogIjxjZW50ZXI+PGI+QW5hbmQgUGFudCwgQmFybmV5IFBlcmV6LCBMaW5hIExvcGV6LCBUb21teSBXaWxjemVrPC9iPjwvY2VudGVyPiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQotLS0NCjxjZW50ZXI+IVtjYWxpZm9ybmlhXShjYWxpZm9ybmlhLnBuZyk8L2NlbnRlcj4NCg0KIyoqSW50cm9kdWN0aW9uKioNCk91ciBnb2FsIGZvciB0aGlzIHByb2plY3Qgd2FzIHRvIGNyZWF0ZSBpbnRlcmVzdGluZyB2aXN1YWxpemF0aW9uIHNob3dpbmcgY29ycmVsYXRpb25zIGJldHdlZW4gY2F1c2VzIG9mIGRlYXRoIGFuZCB0aGUgZGVtb2dyYXBoaWMgdHJlbmRzIGluIHRoZSB6aXAgY29kZXMgb2YgQ2FsaWZvcm5pYS4gDQoNCkluIG9yZGVyIHRvIGRvIHNvIHdlIGFyZSBjbGVhbmluZyBkaXJ0eSBaaXAgY29kZSBkYXRhIGZyb20gdGhlIFVTIENlbnN1cyBhcyB3ZWxsIGFzIHppcCBjb2RlIGRhdGEgY29ycmVzcG9uZGluZyB0byBjYXVzZSBvZiBkZWF0aC4gVGhlc2UgZGF0YSBzZXRzIGFyZSBhdmFpbGFibGUgb24gZGF0YS53b3JsZCBhbmQgd2VyZSBqb2luZWQgdXNpbmcgVGFibGVhdSBhbmQgUiwgd2hpY2ggd2UgdXNlZCB0byBwcm9kdWNlIHRoZSB2aXN1YWxpemF0aW9ucyB3ZSBwcmVzZW50IGluIHRoaXMgZG9jdW1lbnQuDQoNClRoZSBmb2xsb3dpbmcgbGlua3MgcmVmZXIgdG8gdGhlIGNlbnN1cyBkYXRhIHVzZWQgZm9yIG91dCB2aXN1YWxpemF0aW9ucy4NCg0KTWVkaWFuIEluY29tZSBkYXRhIHdhcyB0YWtlbiBmcm9tIHRoZSBmb2xsb3dpbmcgbGluayB0byB0aGUgVVMgQ2Vuc3VzIERhdGEgaW4gZGF0YS53b3JsZDoNCmh0dHBzOi8vZGF0YS53b3JsZC91c2NlbnN1c2J1cmVhdS9hY3MtMjAxNS01LWUtaW5jb21lDQoNCk1lZGlhbiBBZ2UgZGF0YSB3YXMgdGFrZW4gZnJvbSB0aGUgZm9sbG93aW5nIGxpbmsgdG8gdGhlIFVTIENlbnN1cyBEYXRhIGluIGRhdGEud29ybGQ6DQpodHRwczovL2RhdGEud29ybGQvdXNjZW5zdXNidXJlYXUvYWNzLTIwMTUtNS1lLWFnZXNleA0KDQpEb21pbmFudCBSYWNlIGRhdGEgd2FzIHRha2VuIGZyb20gdGhlIGZvbGxvd2luZyBsaW5rIHRvIHRoZSBVUyBDZW5zdXMgRGF0YSBpbiBkYXRhLndvcmxkOg0KaHR0cHM6Ly9kYXRhLndvcmxkL3VzY2Vuc3VzYnVyZWF1L2Fjcy0yMDE1LTUtZS1yYWNlDQoNCiMqKlIgQ29uZmlndXJhdGlvbioqDQpCZWxvdyB3ZSBkaXNwbGF5IG91ciBzZXNzaW9uSW5mbygpLg0KDQpgYGB7ciBzZXNzaW9uSW5mb30NCnNlc3Npb25JbmZvKHBhY2thZ2U9TlVMTCkNCmBgYA0KDQojKipEYXRhIFN1bW1hcnkqKg0KVGhlIGZvbGxvd2luZyBoZWFkcyBhbmQgc3VtbWFyaWVzIGRlbW9uc3RyYXRlIHRoZSBkYXRhIHRoYXQgd2lsbCBiZSBqb2luaW5nIHZpYSBkYXRhLndvcmxkIGluIG91ciBxdWVyaWVzIHdoZW4gdXNpbmcgc2hpbnkuIFRoaXMgZGF0YSB3aWxsIGFsc28gYmUgam9pbmVkIGluIHRhYmxlYXUgZm9yIHRoZSBjb3JyZXNwb25kaW5nIHZpc3VhbGl6YXRpb25zLiAgDQoNCg0KIyoqUHJvY2Vzc2luZyB0aGUgRGF0YSoqDQpUaGUgY3N2IGZpbGVzIGNvbnRhaW5pbmcgb3VyIGRhdGEgb2YgaW50ZXJlc3Qgd2VyZSBwYXNzZWQgdGhyb3VnaCBpbmRpdmlkdWFsIEVUTCBmaWxlcyBmb3IgY2xlYW5pbmcuIEluIHRoaXMgcHJvY2VzcyBzcGFjZXMgYXJlIGluY2x1ZGVkIGJldHdlZW4gdXBwZXIgYW5kIGxvd2VyIGNhc2VkIGxldHRlcnMgYW5kIGFtcGVyc2FuZHMgYXJlIGNoYW5nZWQgdG8gdGhlIHdvcmQgImFuZCIuVGhlc2Ugc3VidGxldGllcyBhbW9uZyBvdGhlcnMgYXJlIGRvbmUgdG8gZWZmZWN0aXZlbHkgdXBsb2FkIHRoZSBkYXRhIGZpbGVzIHRvIGRhdGEud29ybGQuIEJlY2F1c2Ugb3VyIGRhdGEgZGlkIG5vdCByZXF1aXJlIG11Y2ggImNsZWFuaW5nIiBvciByZW5hbWluZyBvZiBjb2x1bW5zLCB3ZSBkaWQgbm90IG5lZWQgdG8gaW5jbHVkZSBpbiBkZXB0aCBjb2RlIGluIHRoZSBFVEwgZmlsZS4gV2UgdXNlZCBtYW55ICJjb29raWUtY3V0dGVyIiBFVEwgZmlsZXMgdG8gY2xlYW4gdGhlIG1hbnkgZmlsZXMgd2UgdXNlZCBmb3Igb3VyIGpvaW5zLiBUaGVzZSBmaWxlcyBpbmNsdWRlICJFVExfbWVkaWFuX2FnZS5SLCBFVExfZG9taW5hbnRfcmFjZS5SLCBFVExfbWVkaWFuX2luY29tZS5SIiBCZWxvdyBpcyBhIHNvdXJjZSBvciBsaW5rIHRvIG9uZSBvZiBvdXIgRVRMIGZpbGVzLiANCg0KQmVsb3cgaXMgYSBzb3VyY2Ugb2Ygb3VyIGV0bCBmaWxlIHVzZWQgdG8gY2xlYW4gb3VyIGRvbWluYW50IHJhY2UgZmlsZSwNCmBgYHtyIGVjaG89RkFMU0V9DQogc291cmNlKCIuLi8wMURhdGEvRVRMX2RvbWluYW50X3JhY2UuUiIpDQpgYGANCg0KVGhlIGZvbGxvd2luZyBzY3JlZW4gc2hvdCBzaG93cyBzb21lIG9mIHRoZSBjb2RlIHVzZWQgdG8gY2xlYW4gdGhlIGRvbWluYW50IHJhY2UgZmlsZS4NCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wMURhdGEvZG9taW5hbnRSYWNlLnBuZyIpDQpgYGANCg0KDQoNCiMqKlRhYmxlYXUgVmlzdWFsaXphdGlvbnMgU3RlcHMqKg0KDQojIyoqU3RlcCAxIC0gUmV0cmlldmluZyBvdXIgRGF0YSoqDQpXZSBwdWxsZWQgaW4gMiBncm91cGVkIGRhdGEgc2V0cyBmcm9tIG91ciBwcm9qZWN0IHRoYXQgb3JpZ2luYXRlZCBmcm9tIHRoZSBVUyBDZW5zdXMgKE1lZGlhbl9JbmNvbWVfUmF3LmNzdiwgYW5kIE1lZGlhbl9BZ2VfUmF3LmNzdikuIEluIGFkZGl0aW9uLCB3ZSBncm91cGVkIGEgc2V0IGZyb20gcmFjZSBkZW9tZ3JhcGhpY3MgQ2Vuc3VzIGRhdGEgdG8gY3JlYXRlIHRoZSBkb21pYW5hdF9yYWNlLmNzdi4gSW4gb3JkZXIgdG8gY3JlYXRlIHRoaXMgZmlsZSwgd2UgcXVlcmllZCB0aGUgb3JnaW5hbCBjZW5zdXMgZGF0YSBpbiBhIHdheSB3ZSBjb3VsZCBkZWZpbmUgdGhlIGRvbWlhbmFudCByYWNlIGluIGVhY2ggemlwIGNvZGUgKHNxbCBjb21tYW5kcyBhdCB0aGUgYm90dG9tIG9mIHRoZSBwcmVzZW50YXRpb24pLkEgbmV3IGNvbHVtbiB3YXMgYWRkZWQgdG8gdGhlIGRhdGEgc2V0IGluZGljYXRpbmcgdGhlIG1vc3QgcmVwcmVzZW50ZWQgcmFjZSBpbiBlYWNoIHppcCBjb2RlLiBXZSB1c2VkIHRoZSBkYXRhLndvcmxkIGNvbm5lY3RvciB0byByZXRyaWV2ZSBldmVyeXRoaW5nIGZyb20gb3VyIGZpbmFsIHByb2plY3Qgc2l0ZSBvbiBkYXRhLndvcmxkLiBUaGlzIGlzIHdoZXJlIHdlIGFsc28gcHVsbGVkIHRoZSBDYXVzZSBvZiBEZWF0aCBkYXRhIHNldC4gRmluYWxseSB3ZSBwdWxsZWQgaW4gYSBkYXRhIGZpbGUgdGhhdCBjb250YWluZWQgQ2FsaWZvcm5pYSB6aXBjb2RlcywgY2F1c2Ugb2YgZGVhdGgsIGFuZCB0aGUgY291bnQgb2YgZWFjaCB0eXBlIHRoYXQgZmVsbCBpbiB0aGF0IGNhdGVnb3J5LiBUaGVzZSBmaWxlcyB3ZXJlIGlubmVyIGpvaW5lZCBvbiBaSVAgQ29kZSB0byBhbmFseXplIGNhdXNlIGFuZCBjb3VudCBvZiBkZWF0aCB0byBtZWRpYW4gaW5jb21lLCBkb21pbmFudCByYWNlLCBhbmQgbWVkaWFuIGFnZSBpbiBlYWNoIFpJUCBDb2RlLg0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9qb2luLnBuZyIpDQpgYGANCg0KIyoqQm94cGxvdCBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCg0KDQojIyoqU3RlcCAxIC0gQm94cGxvdCBPdmVydmlldyoqDQpJbiBvcmRlciB0byBjcmVhdGUgb3VyIGJveCBwbG90IHdlIHNldCBjYXVzZXMgb2YgZGVhdGhzIGFzIHRoZSBjb2x1bW5zIHdoaWNoIGNhbiBiZSBzZWVuIGFsb25nIHRoZSB4LWF4aXMgb2YgdGhlIHBsb3QuIFRoZSByb3cgYXJlIHNldCBhcyB0aGUgY291bnQgb2YgZGVhdGhzIGFzIHNlZW4gb24gdGhlIHktYXhpcyBvZiB0aGUgcGxvdC4gRWFjaCB6aXAgY29kZSBoYXMgYSBjb3JyZXNwb25kaW5nIHBvaW50IG9uIHRoZSBib3hwbG90IGZvciBlYWNoIGNhdXNlIG9mIGRlYXRoLiBXZSBzZXQgZG9taW5hbnQgcmFjZSBhcyB0aGUgY29sb3Igb2YgdGhlIHBvaW50cyBpbiB0aGUgcGxvdC4gVGhlcmVmb3JlLCB0aGUgY29sb3Igb2YgZWFjaCBwb2ludCBkZXBlbmRzIG9uIGVhY2ggemlwIGNvZGUncyBkb21pbmFudCByYWNlLiBUaGUgYm94ZXMgYWxvbmcgZWFjaCBjb2x1bW4gbWFyayB0aGUgMjV0aCB0byA3NXRoIHBlcmNlbnRpbGUgb2YgY291bnRzIG9mIGRlYXRocyBwZXIgemlwIGNvZGUgZm9yIGVhY2ggY2F1c2UuIFRoZSB3aGlza2VycyBtYXJrIHRoZSBoaWdoZXN0IGFuZCBsb3dlc3QgY291bnQgdmFsdWVzIGNvbnNpZGVyZWQgdG8gbm90IGJlIG91dGxpZXJzLiANCg0KIyMqKlN0ZXAgMiAtIEZpbHRlcioqDQpXZSBhZGRlZCBhIGZpbHRlciB0byB0aGlzIGJveHBsb3QgaW4gb3JkZXIgdG8gZGVmaW5lIHRoZSByYW5nZSBvZiB0aGUgbWVkaWFuIGluY29tZXMgb2YgdGhlIHppcGNvZGVzIGRpc3BseWVkLiANCg0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAwcHgiLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvVGFibGVhdV9TY3JlZW5zaG90cy9Cb3hwbG90MS5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvVGFibGVhdV9TY3JlZW5zaG90cy9Cb3hwbG90Mi5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvVGFibGVhdV9TY3JlZW5zaG90cy9Cb3hwbG90My5wbmciKQ0KDQpgYGANClRoaXMgb2JzZXJ2YXRpb24gc2VlbXMgcmVsYXRpdmVseSBvZGQuIElmIGV2ZW4ganVzdCBsb29raW5nIGF0IHRoZSBnZW5lcmFsIGRlYXRoIHJhdGUgd2Ugc2VlIHRoYXQgaXQgc3RhcnRzIGhpZ2gsIGdvZXMgZG93biwgdGhlbiBnb2VzIGJhY2sgdXAgYWdhaW4gYXMgaW5jb21lIGlzIHN0ZWFkaWx5IGluY3JlYXNpbmcuIElmIHlvdSBhcmUgb25seSBvcGVyYXRpbmcgdW5kZXIgdGhlIHByZW1pc2UgdGhhdCBtb3JlIGluY29tZSBtZWFucyBiZXR0ZXIgaGVhbHRoY2FyZS9saWZlc3R5bGUgd2hpY2ggbWVhbnMgZ3JlYXRlciBsb25nZXZpdHkgdGhpcyBzZWVtcyBjb3VudGVyIGludHVpdGl2ZS4gSG93ZXZlciBpZiB5b3UgY29uc2lkZXIgd2hvIGlzIG1ha2luZyB0aGUgaGlnaGVyIGluY29tZSBhbW91bnRzIGl0IG1ha2VzIG1vcmUgc2Vuc2UuIA0KDQo8Y2VudGVyPiFbaW5jb21lXShpbmNvbWVfYWdlLnBuZyk8L2NlbnRlcj4NCg0KIyMqKkhpc3RvZ3JhbSBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1RhYmxlYXVfU2NyZWVuc2hvdHMvMi5wbmciKQ0KDQpgYGANCiMjKipTY2F0dGVyIFBsb3QgVmlzdWFsaXphdGlvbiBTdGVwcyoqDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9UYWJsZWF1X1NjcmVlbnNob3RzLzMucG5nIikNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1RhYmxlYXVfU2NyZWVuc2hvdHMvNS5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvVGFibGVhdV9TY3JlZW5zaG90cy8xMC5wbmciKQ0KYGBgDQoNCiMjKipDcm9zc3RhYiBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCg0KIyMjKipTdGVwIDEgLSBUYWJsZSBDYWN1bGF0aW9ucyoqDQoNClRoZSB0d28gdGFibGUgY2FsY3VsYXRpb24gcGlsbHMgd2UgaW5jbHVkZWQgaW4gb3VyIFRhYmxlYXUgZmlsZSB3ZXJlICJDYWxjdWxhdGVkIERpZmYgZnJvbSBBdmciIGFuZCAiQ2FsY3VsYXRlZCBXZWlnaHRlZCBEaWZmIGZyb20gQXZnLiIgUmVmZXJlbmNlIGxpbmVzIHdlcmUgYWxzbyBpbmNsdWRlZCBpbiBvdXIgcHJvamVjdC4gVGhpcyBjYW4gYmUgc2VlbiBpbiB0aGUgIlJhY2UgVGFibGUgQ2FsY3VsYXRpb25zIiB2aXN1YWxpemF0aW9uLiBJbiB0aGlzIGNhc2UsIHJlZmVyZW5jZSBsaW5lcyB3ZXJlIHVzZWQgdG8gZGVwaWN0IGFuIGF2ZXJhZ2UgY291bnQgb2YgZGVhdGggYnkgcmFjZSBmb3IgZWFjaCBjYXVzZSBvZiBkZWF0aC4gDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1RhYmxlYXVfU2NyZWVuc2hvdHMvNi5wbmciKQ0KYGBgDQoNCiMjKipCYXJjaGFydCBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1RhYmxlYXVfU2NyZWVuc2hvdHMvNy5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvVGFibGVhdV9TY3JlZW5zaG90cy85LnBuZyIpDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9UYWJsZWF1X1NjcmVlbnNob3RzLzgucG5nIikNCmBgYA0KDQojIyMqKlN0ZXAgMSAtIFJldHJpZXZpbmcgb3VyIERhdGEqKg0KV2UgcHVsbGVkIGluIDMgZGF0YSBzZXRzIGZyb20gb3VyIHByb2plY3QgdGhhdCBvcmlnaW5hdGVkIGZyb20gdGhlIFVTIENlbnN1cyAobWVkaWFuX2luY29tZS5jc3YsIG1lZGlhbl9hZ2UuY3N2LCBhbmQgZG9taW5hbnRfcmFjZS5jc3YpLldlIGZvdW5kIHRoYXQgc29tZSBjb2x1bW5zIGluIHRoZXNlIGRhdGEgc2V0cyBoYWQgdG8gYmUgZ3JvdXBlZCwgc28gd2UgaW5jbHVkZWQgb3VyIFNRTCBjb2RlIGF0IHRoZSBib3R0b20gb2YgdGhlIHByb2plY3QgdGhhdCBkZXNjcmliZXMgaG93IHdlIGNyZWF0ZWQgYmlucyBmb3IgYWdlcywgaW5jb21lcywgYW5kIGRvbWluYW50IHJhY2VzLkZvciB0aGlzIHNhbWUgcmVhc29uLCB3ZSBkaWQgbm90IHB1bGwgZnJvbSB0aGUgQ2Vuc3VzIEJ1cmVhdSdzIGRhdGEuIEluc3RlYWQsIHdlIHVzZWQgdGhlIGRhdGEud29ybGQgY29ubmVjdG9yIHRvIHJldHJpZXZlIGV2ZXJ5dGhpbmcgZnJvbSBvdXIgcHJvamVjdCA2IHNpdGUgb24gZGF0YS53b3JsZC4gVGhpcyBpcyB3aGVyZSB3ZSBhbHNvIHB1bGxlZCB0aGUgQ2F1c2Ugb2YgRGVhdGggZGF0YSBzZXQuIFRoZXNlIGZpbGVzIHdlcmUgaW5uZXIgam9pbmVkIG9uIFpJUCBDb2RlIHRvIGFuYWx5emUgY2F1c2UgYW5kIGNvdW50IG9mIGRlYXRoIHRvIG1lZGlhbiBpbmNvbWUsIGRvbWluYW50IHJhY2UsIGFuZCBtZWRpYW4gYWdlIGluIGVhY2ggWklQIENvZGUuDQoNCiMjIyoqU3RlcCAyIC0gQmFyY2hhcnQgT3ZlcnZpZXcqKg0KV2UgY3JlYXRlZCBiYXJjaGFydHMgYmV0d2VlbiBlaXRoZXIgbWVkaWFuIGluY29tZSwgZG9taW5hbnQgcmFjZSwgb3IgbWVkaWFuIGFnZSAob25lIGJsdWUpIGFuZCBjYXVzZSBvZiBkZWF0aCAoc2Vjb25kIGJsdWUpIGluIHRoZSByb3cgc2xvdC4gVGhpcyB0aGVuIGxpc3RzIGFsbCB0aGUgY2F1c2VzIG9mIGRlYXRoIGFuZCB3aXRoaW4gZWFjaCBjYXVzZSBvZiBkZWF0aCBsaXN0cyBhIHJvdyBmb3IgZWl0aGVyIG1lZGlhbiBhZ2UsIG9yIGRvbWluYW50IHJhY2UuICBBIHN1bSBvZiB0aGUgY291bnQgb2YgZGVhdGhzIChncmVlbikgd2FzIGFkZGVkIGFzIHRoZSBjb2x1bW4gb2YgdGhlIGJhcmNoYXJ0cy4gV2l0aCB0aGlzIGNvdW50IHdlIGNhbiBjb21wYXJlIHRoZSBudW1iZXIgb2YgcGVvcGxlIGR5aW5nIG9mIGEgY2VydGFpbiBjYXVzZSBvZiBkZWF0aCBhY3Jvc3MgemlwIGNvZGVzIG9mIGRpZmZlcmVudCBtZWRpYW4gYWdlcyAoZm9yIGV4YW1wbGUpLiBOb25ldGhlbGVzcywgd2UgY29uc2lkZXJlZCB0aGF0IGNlcnRhaW4gcmFjZXMsIGFuZCBhZ2VzIHdlcmUgb3ZlciByZXByZXNlbnRlZCBpbiBvdXIgZGF0YS4gVGhlcmVmb3JlLCB3ZSBjcmVhdGVkIGEgY2FsY3VsYXRlZCBmaWVsZCB0byBhZGQgdG8gb3VyIGNvbHVtbiBzbG90IG5hbWVkIFdlaWdodGVkIFJhY2UvQWdlIERlYXRocyB3aGljaCB3aWxsIGJlIGRlc2NyaWJlZCBpbiB0aGUgZm9sbG93aW5nIGJ1bGxldC4gVGhpcyBjYWxjdWxhdGVkIGZpZWxkIGFsbG93cyB1cyB0byByZWNvZ25pemUgd2hpY2ggcG9wdWxhdGlvbnMgYXJlIG1vcmUgbGlrZWx5IHRvIGRpZSBvZiBjZXJ0YWluIGNhdXNlcyB0aGFuIHByZWRpY3RpbmcgZnJvbSBhIHJhdyBjb3VudCBvZiBkZWF0aHMuICANCg0KDQojIyMqKlN0ZXAgMyAtIENhbGN1bGF0ZWQgRmllbGRzKioNCkZ1cnRoZXJtb3JlLCBhcyBtZW50aW9uZWQgcHJldmlvdXNseSB3ZSBjcmVhdGVkIHRocmVlIGNhbGN1bGF0ZWQgZmllbGQgcHJvZHVjaW5nIGEgIFdlaWdodGVkIGNvdW50IG9mIERlYXRocyBmb3IgaW5jb21lLCBhZ2UsIGFuZCBkb21pbmFudCByYWNlLiBUbyBpbGx1c3RyYXRlIHRoZSBwcm9jZXNzIHdlIGNhbiB0YWtlIHRoZSBkZWF0aHMgYnkgcmFjZSBiYXJjaGFydCBhcyBhbiBleGFtcGxlLiBUaGUgY2FsY3VsYXRlZCBmaWVsZCB0YWtlcyB0aGUgY291bnQgb2YgZGVhdGhzIGluIGEgemlwIGNvZGUgZG9taW5hbnRlZCBieSBhIGNlcnRhaW4gcmFjZSBkdWUgdG8gYSBjZXJ0YWluIGNhdXNlIGFuZCBkaXZpZGVzIGl0IGJ5IHRoZSB0b3RhbCBjb3VudCBvZiBkZWF0aHMgaW4gemlwIGNvZGVzIHdpdGggdGhhdCBkb21pbmFudCByYWNlIChyZWdhcmRsZXNzIG9mIGNhdXNlIG9mIGRlYXRoKS4gVGhpcyBjYWxjdWxhdGVkIGZpZWxkIGNyZWF0ZXMgYSBwcm9wb3J0aW9uIG9mIGRlYXRocyBkdWUgdG8gY2VydGFpbiBjYXVzZXMgdGhhdCBhY2NvdW50cyBmb3Igb3ZlcnJlcHJlc2VudGVkIHJhY2VzLiBXZSBjYW4gdGhlbiBjb21wYXJlIHdlaWdodGVkIHByb3BvcnRpb25zIHRvIG1vcmUgYWNjdXJhdGVseSBwcmVkaWN0IHdoaWNoIHppcCBjb2RlcyBhcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSBkZWF0aHMgb2YgYSBjZXJ0YWluIGNhdXNlIHdpdGggcmVzcGVjdCB0byB0aGVpciBkb21pbmFudCByYWNlLiBUaGlzIHNhbWUgcHJvY2VzcyB3YXMgZm9sbG93ZWQgZm9yIG1lZGlhbiBpbmNvbWUsIGFuZCBtZWRpYW4gYWdlLiBUaGVzZSB3ZWlnaHRlZCBjb3VudCBvZiBkZWF0aCB3YXMgYWRkZWQgdG8gdGhlIGNvbHVtbnMgbG90IG9mIG91ciBiYXJjaGFydHMgdG8gY3JlYXRlIGEgc2VwYXJhdGUgYmFyY2hhcnQgbmV4dCB0byByYXcgZGVhdGggY291bnQgY29sdW1ucy4gVGhlIHJvd3Mgd2VyZSBtYWludGFpbmVkIHRoZSBzYW1lIGFuZCBjb2x1bW5zIHdlcmUgYWRkZWQgdG8gcmVwcmVzZW50IHRoZSB3ZWlnaHRlZCBjb3VudCBvZiBkZWF0aHMuDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL0NhbGN1bGF0ZWRGaWVsZHMucG5nIikNCmBgYA0KDQoNCiMjKipCYXJjaGFydCBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1RhYmxlQ2FsY3VsYXRpb25zLnBuZyIpDQpgYGANCg0KIyMjIyMqKlJlZmVyZW5jZSBMaW5lcyoqIA0KDQpXZSBkZWNpZGVkIHRvIHVzZSBhbiBhdmVyYWdlIHJlZmVyZW5jZSBsaW5lIGZvciBhbGwgb3VyIGJhcmNoYXJ0cy4gVGhpcyB0YWtlcyB0aGUgYXZlcmFnZSBkZWF0aCBjb3VudCBiZXR3ZWVuIGRpZmZlcmVudCByYWNlIGRvbWluYW50ZWQgemlwIGNvZGVzIChmb3IgZWF4bXBsZSkgZm9yIGEgY2VydGFpbiBjYXVzZSBvZiBkZWF0aCBhbmQgY3JlYXRlcyBhIHJlcHJlc2VudGF0aXZlIGxpbmUgYWxvbmcgb3VyIGNvbHVtbnMgdG8gdmlzdWFsaXplIHRoZSBhdmVyYWdlIGNvdW50LiBJbiBhZGRpdGlvbiwgdGhpcyBhdmVyYWdlIGxpbmUgd2FzIGNyZWF0ZWQgZm9yIG91ciB3ZWlnaHRlZCBkZWF0aCBjb3VudC4gVGhlIGF2ZXJhZ2Ugd2VpZ2h0ZWQgZGVhdGggY291bnQgYWNyb3NzIGRpZmZlcmVudCByYWNlIGRvbWluYW50ZWQgemlwIGNvZGVzIChmb3IgZXhhbXBsZSkgd2FzIGRpc3BsYXllZCBmb3IgZWFjaCBjdWFzZSBvZiBkZWF0aCBhcyBhIGxpbmUgYWNvcnNzIG91ciBjb2x1bW5zLg0KDQpBcyBzaG93biBiZWxvdywgcmVmZXJlbmNlIGxpbmVzIHdlcmUgaW1wbGVtZW50ZWQgaW4gdGhlICJBZ2UgUmVmZXJlbmNlIExpbmVzIiB2aXN1YWxpemF0aW9uIHRvIGRlcGljdCB0aGUgdGhlIGF2ZXJhZ2UgY291bnQgb2YgZGVhdGhzIGJ5IGFnZSBncm91cCBmb3IgZWFjaCBjYXVzZSBvZiBkZWF0aC4gOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHdlcmUgYWxzbyBkaXNwbGF5ZWQgb24gdGhpcyB2aXN1YWxpemF0aW9uIHRvIHNob3cgdGhlIHJlYWRlciB0aGF0IHRoZSB0cnVlIGNvdW50IG9mIGRlYXRocyB3aXRoaW4gdGhlIGFjdHVhbCBhZ2UgZ3JvdXBzIHdvdWxkIGZhbGwgd2l0aGluIHRoZSBwdXJwbGUgaGlnaGxpZ2h0ZWQgcmFuZ2UgOTUlIG9mIHRoZSB0aW1lLiANCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL0FnZVJlZmVyZW5jZUxpbmVzMS5wbmciKQ0KYGBgDQojIyMjIyoqRm9ybWF0dGluZyoqDQoNCkZvcm1hdHRpbmcgaXMgZGVwaWN0ZWQgaW4gb3VyIEluY29tZSBJRCBTZXRzIEJhciBjaGFydC4gQmVjYXVzZSBvdXIgeS1heGlzIHVuaXRzIGFyZSBJbmNvbWUsIHRoZXkgYXJlIGZvcm1hdHRlZCBhcyBDdXJyZW5jeS4gICBBbGwgb2YgdGhlc2UgaXRlbXMgYXJlIGRlcGljdGVkIGluIHRoZSB2aXN1YWxpemF0aW9ucyBiZWxvdy4gDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9Gb3JtYXR0aW5nLnBuZyIpDQpgYGANCg0KIyMjIyMqKklEIFNldHMqKg0KDQpJbiBvcmRlciB0byB1c2UgSUQgc2V0cyB3ZSBkZWZpbmVkICdhdCByaXNrIGluY29tZSBicmFja2V0cycuIFRoaXMgd2FzIGRvbmUgYnkgY3JlYXRpbmcgYSBiYXIgZ3JhcGggbGlzdGluZyBkaWZmZXJlbnQgbWVkaWFuIGluY29tZXMgYXMgYmlucyBhbmQgY3JlYXRpbmcgY29sdW1ucyB3aXRoIHdlaWdodGVkIGRlYXRoIGNvdW50cyBmb3IgemlwY29kZXMgb2YgZWFjaCBtZWRpYW4gaW5jb21lIChpcnJlc3BlY3RpdmUgb2YgY2F1c2Ugb2YgZGVhdGgpLiBaaXBjb2RlcyBvZiBtZWRpYW4gaW5jb21lcyB3aXRoIG1vcmUgdGhhbiBzZXZlbiB3ZWlnaHRlZCBkZWF0aCBjb3VudHMgd2VyZSBjYXRlZ29yaXplZCBhcyAnYXQgcmlzaycuIFRoaXMgaXMgdGhlbiB0YWtlbiB0byBjcmVhdGUgYW5vdGhlciBiYXIgZ3JhcGggd2l0aCBjYXVzZXMgb2YgZGVhdGggbGlzdGVkIGFzIHRoZSBiaW5zIGFuZCB3ZWlnaHRlZCBjb3VudCBvZiBkZWF0aCBhcyB0aGUgcGFyYW1ldGVyIG9mIHRoZSBoZWlnaHQgb2YgdGhlIGJhcnMuIEJ5IGFwcGx5aW5nIG91ciAnYXQgcmlzaycgSUQgU2V0IHdlIGRpdmlkZSB0aGUgYmFycyBpbiB0byBhIHByb3BvcnRpb24gYXQgcmlzayBhbmQgYSBwcm9wb3J0aW9uIG91dCBvZiByaXNrLiBUaGVyZWZvcmUsIGZvciBlYWNoIGNhdXNlIG9mIGRlYXRoIHdlIGNhbiByZWNvZ25pemUgdGhlIGFtb3VudCBvZiB3ZWlnaHRlZCBkZWF0aHMgaW4gemlwIGNvZGVzIHdpdGggYSB3ZWlnaHRlZCBjb3VudCBvZiBkZWF0aHMgYWJvdmUgdGhlIHRoZXJzaG9sZCBvZiBzZXZlbiB3ZWlnaHRlZCBkZWF0aHMuIA0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9TZXRzLnBuZyIpDQpgYGANCg0KIyoqVGFibGVhdSBWaXN1YWxpemF0aW9ucyoqDQojIyMjKipWaXN1YWxpemF0aW9uIFR5cGUgMSAtIEJhckdyYXBocyoqDQoNClRoZSBmb2xsb3dpbmcgdmlzdWFsaXphdGlvbnMgd2VyZSBjcmVhdGVkIHRvIGdpdmUgYW4gdW5kZXJzdGFuZGluZyBvZiBob3cgb3VyIHdlaWdodGVkIGRlYXRoIGNvdW50cyB3YXMgY3JlYXRlZCBhbmQgd2hhdCBvdXIgY2FsY3VsdGVkIGZpZWxkIHJlcHJlc2VudHMuDQoNCg0KIyMjIyoqVmlzdWFsaXphdGlvbiBUeXBlIDIgLSBCYXIgQ2hhcnRzKioNCg0KVGhlIGZvbGxvd2luZyBiYXJjaGFydHMgd2VyZSBjcmVhdGVkIHdpdGggdGhlIHByb2Nlc3MgZGVzY2liZWQgaW4gdGhlIFRhYmxlYXUgdmlzdWFsaXphdGlvbiBzdGVwcy4gIA0KDQoNCiMjIyMjKipEb21pbmFudCBSYWNlIEJhcmNoYXJ0KioNCg0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAwcHgiLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvUmFjZVRhYmxlQ2FsY3VsYXRpb25zMS5wbmciKQ0KYGBgDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9SYWNlVGFibGVDYWxjdWxhdGlvbnMyLnBuZyIpDQpgYGANCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1JhY2VUYWJsZUNhbGN1bGF0aW9uczMucG5nIikNCmBgYA0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAwcHgiLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvUmFjZVRhYmxlQ2FsY3VsYXRpb25zNC5wbmciKQ0KYGBgDQoNCkxvb2tpbmcgYXQgdGhlIHRhYmxlcyBvbiB0aGUgbGVmdCwgd2hpY2ggc2hvdyB0aGUgdW53ZWlnaHRlZCBkZWF0aCBjb3VudHMsIG9uZSB3b3VsZCB0aGluayB3aGl0ZSBwZW9wbGUgYXJlIG1vcmUgbGlrZWx5IHRvIGRpZSBmcm9tIGp1c3QgYWJvdXQgZXZlcnl0aGluZy4gSG93ZXZlciwgdGhpcyBpcyBzaW1wbHkgYmVjYXVzZSB0aGVyZSBhcmUgbW9yZSB3aGl0ZXMgdGhhbiBhbnkgb3RoZXIgcmFjZSBpbiB0aGUgcG9wdWxhdGlvbiwgbWVhbmluZyB0aGV5IGhhdmUgbW9yZSBkZWF0aHMuDQpJbiBvcmRlciB0byBhY2NvdW50IGZvciB0aGlzLCB3ZSBpbnN0ZWFkIHZpc3VhbGl6ZWQgcmFjZSBhbmQgY2F1c2Ugb2YgZGVhdGggdXNpbmcgd2VpZ2h0ZWQgcmFjZSBkZWF0aHMgKHNlZSAiQ3JlYXRlZCBXZWlnaGVkIFJhY2UgRGVhdGhzIiB0YWIpLiBUaGlzIGVhc2lseSBhbGxvd3MgdXMgdG8gY29tcGFyZSBob3cgbGlrZWx5IGRpZmZlcmVudCByYWNlcyBhcmUgdG8gZGllIG9mIGEgZ2l2ZW4gY2F1c2Ugb2YgZGVhdGguDQpPdXIgaW50ZXJlc3RpbmcgZmluZGluZ3MgaXMgdGhhdCBvZiB0aGUgdGhyZWUgaGlnaGVzdCBjYXVzZXMgb2YgZGVhdGhzOiBjYW5jZXIsIGhlYXJ0IGRpc2Vhc2UsIGFuZCAib3RoZXIiLCBibGFja3MgYXJlLCBvbiBhdmVyYWdlLCBtb3JlIGxpa2VseSB0byBkaWUgdGhhbiBhbnkgb3RoZXIgcmFjZSwgdGFraW5nIGludG8gYWNjb3VudCB0aGVpciBudW1iZXJzIGluIHRoZSB0b3RhbCBwb3B1bGF0aW9uLg0KDQojIyMjIyoqTWVkaWFuIEFnZSBCYXJjaGFydCoqDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL0FnZVJlZmVyZW5jZUxpbmVzMS5wbmciKQ0KYGBgDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9BZ2VSZWZlcmVuY2VMaW5lczIucG5nIikNCmBgYA0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAwcHgiLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvQWdlUmVmZXJlbmNlTGluZXMzLnBuZyIpDQpgYGANCg0KTG9va2luZyBhdCB0aGUgdGFibGVzIG9uIHRoZSBsZWZ0LCB3aGljaCBzaG93IHRoZSB1bndlaWdodGVkIGRlYXRoIGNvdW50cywgb25lIHdvdWxkIHRoaW5rIHBlb3BsZSB3aG8gbWFrZSBiZXR3ZWVuIDMwIGFuZCA0MCB0aG91c2FuZCBkb2xsYXJzIHBlciB5ZWFyIGFyZSBtb3JlIGxpa2VseSB0byBkaWUgZnJvbSBqdXN0IGFib3V0IGV2ZXJ5dGhpbmcuIEhvd2V2ZXIsIHRoaXMgaXMgc2ltcGx5IGJlY2F1c2UgdGhlcmUgYXJlIG1vcmUgcGVvcGxlIGluIHRoYXQgaW5jb21lIHJhbmdlIHRoYW4gYW55IG90aGVyIGluIHRoZSBwb3B1bGF0aW9uLCBtZWFuaW5nIHRoZXkgaGF2ZSBtb3JlIGRlYXRocy4NCkluIG9yZGVyIHRvIGFjY291bnQgZm9yIHRoaXMsIHdlIGluc3RlYWQgdmlzdWFsaXplZCByYWNlIGFuZCBjYXVzZSBvZiBkZWF0aCB1c2luZyB3ZWlnaHRlZCBpbmNvbWUgZGVhdGhzIChzZWUgIkNyZWF0ZWQgV2VpZ2hlZCBJbmNvbWUgRGVhdGhzIiB0YWIpLiBUaGlzIGVhc2lseSBhbGxvd3MgdXMgdG8gY29tcGFyZSBob3cgbGlrZWx5IHBlb3BsZSBpbiBkaWZmZXJlbnQgaW5jb21lIHJhbmdlcyBhcmUgdG8gZGllIG9mIGEgZ2l2ZW4gY2F1c2Ugb2YgZGVhdGgNCk91ciBpbnRlcmVzdGluZyBmaW5kaW5nIGlzIHRoYXQgaGVhcnQgZGlzZWFzZSBhbmQgY2FuY2VyIGFyZSB0aGUgbW9zdCBsaWtlbHkgY2F1c2Ugb2YgZGVhdGggYWNyb3NzIGFsbCBhZ2UgZ3JvdXBzLiANCkZvciBjYW5jZXIgd2UgY2FuIG5vdGljZSB0aGF0IGEgbGFyZ2VyIHByb3BvcnRpb24gb2YgcGVvcGxlIGluIGFnZSBncm91cHMgYmVsb3cgNTAgeWVhcnMgYXJlIGR5aW5nIG9mIGNhbmNlciBjb21wYXJlZCB0byBwZW9wbGUgaW4gYWdlIGdyb3VwcyBvZiA2MCBhbmQgYWJvdmUuDQogDQoNCiMjIyMqKlZpc3VhbGl6YXRpb24gMyAtIElEIFNldHMgLSBJbmNvbWUgSUQgLSBJbiwgT3V0KioNCg0KVGhlIHZpc3VhbGl6YXRpb24gYmVsb3cgdXNlcyBTZXRzIHRvIGRlcGljdCBpbmNvbWUgYnJhY2tldHMgdGhhdCBhcmUgZWl0aGVyICJhdC1yaXNrIiIgb3Igbm90ICJhdC1yaXNrLiIgSW4gdGhpcyBjYXNlLCAiYXQtcmlzayIgcmVmZXJzIHRvIGluY29tZSBicmFrY2V0cyB0aGF0IGhhdmUgYSB3ZWlnaHRlZCBkZWF0aCByYXRlIG9mIDcgb3IgbW9yZS4gVGhlIG9yYW5nZSBwb3J0aW9ucyBvZiBlYWNoIGJhciBzaG93IHRoZSBhbW91bnQgb2YgZGVhdGhzIHdpdGhpbiB0aGUgImF0LXJpc2sgaW5jb21lIGJyYWNrZXRzIiBzZXQuIFRoZSBncmV5IHBvcnRpb25zIGFyZSB0aG9zZSBvdXQgb2YgdGhlIHNldCwgYXMgdGhlaXIgd2VpZ2h0ZWQgZGVhdGggcmF0ZSBpcyBiZWxvdyA3Lg0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9JbmNvbWVJRFNldHMtSW4tT3V0LnBuZyIpDQpgYGANCkluIG9yZGVyIHRvIGNyZWF0ZSB0aGUgc2V0LCB3ZSBzZWxlY3RlZCB0aGUgaW5jb21lIGJyYWNrZXRzIHRoYXQgaGFkIGEgd2VpZ2h0ZWQgaW5jb21lIGRlYXRoIHJhdGUgZ3JlYXRlciB0aGFuIDcuIFRoZXNlIHdlcmUgaW5jbHVkZWQgaW4gdGhlICJJbiIgc2V0Lg0KDQojKipTaGlueSBWaXN1YWxpemF0aW9uIFN0ZXBzKioNCkxpbms6IGh0dHBzOi8vYW5hbmRwYW50LnNoaW55YXBwcy5pby9wcm9qZWN0X2ZpbmFsLw0KDQpUaGUgc2hpbnkgYXBwIGNyZWF0ZXMgYSBiYXJjaGFydCB1c2luZyBjYXVzZXMgb2YgZGVhdGggYW5kIGVpdGhlciBtZWRpYW4gaW5jb21lLCBtZWRpYW4gYWdlLCBvciBkb21pbmFudCByYWNlLiBUaGlzIGRhdGEgaXMgYnJvdWdodCBpbiBmcm9tIHRoZSBkYXRhLndvcmxkIGZpbGVzIHdoaWNoIGpvaW4gY2Vuc3VzIGRhdGEgdG8gdGhlIGNhdXNlcyBvZiBkZWF0aCBmaWxlcy4gVGhpcyBpcyBjcmVhdGVkIHdpdGggYW4gaW5uZXIgam9pbiBvbiB0aGUgemlwIGNvZGUgaW4gYm90aCBmaWxlcy4gVGhlIFNRTCB0byBqb2luIGlzIGZvdW5kIGluIHRoZSBzZXJ2ZXIgY29kZSBmb3Igb3VyIHNoaW55IGFwbGljYXRpb24uIA0KDQpUaGUgdXNlciBzaG91bGQgY2xpY2sgb24gdGhlIGdldCBkYXRhIGJ1dHRvbi4gVGhpcyBidXR0b24gc2VuZHMgYSBTUUwgcXVlcnkgdG8gZGF0YS53b3JsZCB0byBqb2luIGFuZCBicmluZyBpbiAgdGhlIGRhdGEgc2V0IG1lbnRpb25lZCBhYm92ZS4gDQoNClRoZSByZXR1cm5lZCBkYXRhIHNldCB3aWxsIGJlIHVzZWQgd2l0aCBnZ3Bsb3QgY29kZSB0byBjcmVhdGUgYmFyY2hhcnRzIHRoYXQgc2hvdyB0aGUgY291bnQgb2YgZGVhdGhzLiBUaGUgcm93cyBvZiB0aGUgYmFyY2hhcnRzIGxpc3QgdGhlIGRpZmZlcmVudCBDYXVzZXMgb2YgRGVhdGhzIGFuZCB0aGUgZGlmZmVyZW50IGJhcmNoYXJ0cyBkZXBpY3QgZGlmZmVyZW50IGFnZSBncm91cHMgKGZvciBleGFtcGxlKS4gRWFjaCBvZiB0aGUgYmFyY2hhcnRzIGhhdmUgYSByZWZlcmVuY2UgbGluZSB0byBzaG93IHRoZSBhdmVyYWdlIGNvdW50IG9mIGRlYXRocyBpbiB0aGF0IGFnZSBncm91cC4NCg0KIyMjIyoqU3RlcCAxKioNCk5hdmlnYXRlIHRvIDAyIFNoaW55IGFuZCBvcGVuIFNlcnZlci5SDQoNCiMjIyMqKlN0ZXAgMioqDQpDbGljayBwdWJsaXNoLg0KDQojIyMjKipTdGVwIDMqKg0KQ2xpY2sgb24gYSB0YWIgaW4gdGhlIHNpZGViYXINCg0KIyMjIyoqU3RlcCA0KioNClNlbGVjdCBnZXQgZGF0YS4gTmF2aWFnYXRlIHRvIHRoZSBncmFwaCB0YWIuIFVzZSB0aGUgc2xpZGVyIHRvIGludGVyYWN0Lg0KDQoNCiMqKlNoaW55IFZpc3VhbGl6YXRpb25zKioNCg0KIyMjKipCb3hwbG90IFRhYioqDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9TaGlueV9TY3JlZW5zaG90cy9nZXR0aW5nZGF0YTEucG5nIikNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1NoaW55X1NjcmVlbnNob3RzL3Bsb3QxLnBuZyIpDQpgYGANCg0KIyMjIyoqSGlzdG9ncmFtIFRhYioqDQpUaGUgaGlzdG9ncmFtIGRpc3BsYXllZCBpcyBjcmVhdGVkIGJ5IGdyb3VwaW5nIHppcCBjb2RlcyBvZiBkaWZmZXJlbnQgbWVkaWFuIGFnZXMgdG8gYmlucyB3aXRoIHJhbmdlcyBvZiA1IHllYXJzLiBUaGUgemlwIGNvZGVzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIG1lZGlhbiBhZ2VzIGFzc2lnbmVkIGJ5IGVhY2ggemlwIGNvZGUgaGF2ZSB0aGVpciBjb3VudCBvZiBkZWF0aHMgc3VtbWVkIGFuZCBkaXNwbGF5ZWQgYXMgdGhlIGNvbHVtbnMgb2YgdGhlIHBsb3QuDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1NoaW55X1NjcmVlbnNob3RzL2dldHRpbmdkYXRhMi5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvU2hpbnlfU2NyZWVuc2hvdHMvcGxvdDIucG5nIikNCmBgYA0KDQojIyMqKlNjYXR0ZXIgUGxvdCBUYWIqKg0KVGhlIHNjYXR0ZXIgcGxvdCBjcmVhdGVkIGhhcyBhIHBvaW50IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNvdW50IG9mIGRlYXRocyBvZiBlYWNoIGNhdXNlIHBlciB6aXAgY29kZS4gVGhlc2UgcG9pbnRzIGFyZSBvcmdhbml6ZWQgYWxvbmcgdGhlIHggYXhpcyBieSB0aGVpciBtZWRpYW4gYWdlIGFuZCBwbGFjZWQgYWxvbmcgdGhlIHkgYXhpcyBieSB0aGVpciBjb3VudCBvZiBkZWF0aHMuIFRoZSBjb2xvciBlYWNoIHBvaW50IGlzIGFzc2lnbmVkIGJ5IHRoZSBjYXVzZSBvZiBkZWF0aCB0aGUgY291bnQgcmVwcmVzZW50cy4gRnJvbSB0aGUgcGxvdCB3ZSBjYW4gbWFrZSB0aGUgb2JzZXJ2YXRpb24gdGhhdCBtZWRpYW4gYWdlIG9mIHppcCBjb2RlcyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgYWJvdXQgYWdlLiBUaGlzIGNhbiBiZSBub3RlZCBieSB0aGUgbGFyZ2VyIGNvdW50IG9mIGRlYXRocyBpbiB0aGUgbWlkZGxlIG9mIHRoZSBwbG90IHNpbmNlIG1vc3QgemlwIGNvZGVzIGhhdmUgbWlkZGxlIGFnZWQgbWVkaWFuIGFnZSB6aXAgY29kZXMuTGVzcyBkZWF0aHMgb2NjdXIgaW4gdGhlIGhpZ2hlc3QgYSBsb3dlc3QgbWVkaWFuIGFnZSB6aXAgY29kZXMuIA0KVGhlIGluY3JlYXNlIGluIGNvdW50IG9mIGRlYXRocyBhcm91bmQgbWVkaWFuIGFnZSBvZiA0MCBjYW4gYmUgZXhwbGFpbmVkIGJ5IHRoZSBpbmNyZWFzZWQgcmlzayBmb3IgaGVhcnQgZGlzZWFzZSBzZWVuIGluIG1hbGVzIG92ZXIgdGhlIGFnZSBvZiA0NS4gSGlnaCBudW1iZXJzIG9mIG92ZXIgNDUgeWVhciBvbGYgbWFsZXMgbWF5IGFjY291bnQgZm9yIHRoZSByaXNlIGluIGRlYXRocy4NCg0KYGBge3IsIG91dC53aWR0aCA9ICIxMDAwcHgiLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvU2hpbnlfU2NyZWVuc2hvdHMvZ2V0dGluZ2RhdGEzLnBuZyIpDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9TaGlueV9TY3JlZW5zaG90cy9wbG90My5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvU2hpbnlfU2NyZWVuc2hvdHMvcGxvdDMuMS5wbmciKQ0KYGBgDQoNCiMjIyMqKkNyb3NzdGFiIFRhYioqDQpUaGUgY3Jvc3MgdGFiIGNyZWF0ZWQgaGFzIGNhdXNlcyBvZiBkZWF0aCBsYWJsZWQgb24gdGhlIHktYXhpcyBhbmQgZG9taW5hbnQgcmFjZSBpbiB0aGUgeC1heGlzLiBFYWNoIGNlbGwgdGhlbiBkaXNwbGF5ZWQgdGhlIHN1bSBvZiB0aGUgY291bnQgb2YgZGVhdGhzIGluIHRoZSB6aXAgY29kZXMgd2l0aCBhIGNlcnRhaW4gZG9taW5hbnQgcmFjZSBkdWUgdG8gYSBjZXJ0YWluIGN1YXNlLiBJbiBhZGRpdGlvbiwgYmVmb3JlIHJldHJpZXZpbmcgdGhlIGRhdGEsIHVzZXJzIGNhbiBkZWZpbmUgdGhlIHJhbmdlcyBjb3JyZXNwb25kaW5nIHRvIGEgbG93LCBtZWRpdW0sIGFuZCBoaWdoIEtQSSB1c2luZyB0aGUgc2xpZGVycyBpbiB0aGUgZGF0YSB0YWIuIFRoZSBLUEkgd2UgY3JlYXRlZCB3YXMgYXZlcmFnZSBkZWF0aHMgcGVyIHppcCBjb2RlLiBUaGlzIEtQSSB0YWtlcyB0aGUgc3VtIG9mIHRoZSBjb3VudHMgYXMgZGlzcGxheWVkIGluIHRoZSBjZWxscyBhbmQgZGl2aWRlcyB0aGF0IGJ5IHRoZSBudW1iZXIgb2YgemlwIGNvZGVzIHRha2VuIGluIHRvIGFjY291bnQgaW4gdGhlIHN1bSBvZiB0aGUgY291bnRzLiBUaGlzIGRlZmluaXRpb24gb2YgaGlnaCwgbG93IGFuZCBtZWRpdW0gYXZlcmFnZSBkZWF0aHMgcGVyIHppcCBjb2RlcyBpcyB0YWtlbiBieSB0aGUgcXVlcnkgc2VudCB0byBkYXRhLndvcmxkLiBUaGUgcXVlcnkgcmV0dXJucyBhIGNvbHVtbiBpbiB0aGUgZGF0YSBkZWZpbmluZyB3aGV0aGVyIGEgY2F1c2Ugb2YgZGVhdGggYW5kIGRvbWluYW50IHJhY2UgY29tYmluYXRpb24gaGFzIGEgaGlnaCwgbG93IG9yIG1lZGl1bSBhdmVyYWdlIGRlYXRocyBwZXIgemlwIGNvZGUuIFRoaXMgcGFyYW1ldGVyIGlzIHRoZW4gdXNlZCB0byBjb2xvciB0aGUgY2VsbHMgaW4gdGhlIGNyb3NzdGFiIHdpdGggaXRzIGNvcnJlc3BvbmRpbmcgbGV2ZWwgb2YgYXZlcmFnZSBkZWF0aHMuICANCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwMHB4IiwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1NoaW55X1NjcmVlbnNob3RzL2dldHRpbmdkYXRhNC5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvU2hpbnlfU2NyZWVuc2hvdHMvcGxvdDQucG5nIikNCmBgYA0KDQoNCg0KIyMjIyoqU2hpbnkgLSAgTWVkaWFuIEluY29tZSBCYXIgQ2hhcnQqKg0KVGhpcyBpbWFnZSBzaG93cyB0aGUgYmFyY2hhcnQgY3JlYXRlZCBmcm9tIGdyb3VwaW5nIHppcCBjb2RlcyBieSBtZWRpYW4gaW5jb21lLg0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9TaGlueV9TY3JlZW5zaG90cy9nZXR0aW5nZGF0YTUucG5nIikNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIuLi8wM1Zpc3VhbGl6YXRpb25zL1NoaW55X1NjcmVlbnNob3RzL3Bsb3Q1LnBuZyIpDQpgYGANCg0KIyMjIyoqQmFyIENoYXJ0IFRhYioqDQpGb3Igb3VyIGJhcmNoYXJ0LCBtZWRpYW4gYWdlIHppcCBjb2RlcyB3ZXJlIGdyb3VwZWQgdG9nZXRoZXIuIFRoZXNlIGdyb3VwaW5ncyB3ZXJlIHRoZW4gZWFjaCBkaXZpZGVkIGJ5IGNhdXNlIG9mIGRlYXRoIGFzIHNlZW4gaW4gdGhlIHkgYXhpcy4gVGhlIGxlbmd0aCBvZiB0aGUgYmFycyBhY2NvdW50IGZvciB0aGUgYXZlcmFnZSBkZWF0aCBjb3VudCBwZXIgemlwIGNvZGUgZm9yIGEgY2VydGFpbiBjYXVzZSBvZiBkZWF0aCBpbiB6aXAgY29kZXMgb2YgYSBjZXJ0YWluIG1lZGlhbiBhZ2UgcmFuZ2UuIEluIGFkZGl0aW9uIGEgcmVmZXJlbmNlIGxpbmUgd2FzIGFkZGVkIHRvIGVhY2ggbWVkaWFuIGFnZSBncm91cGluZy4gVGhpcyBsaW5lIGluZGljYXRlcyB0aGUgYXZlcmFnZSBvZiB0aGUgYXZlcmFnZSBkZWF0aHMgcGVyIHppcCBjb2RlcyBpbiBlYWNoIGdyb3VwaW5nLiBUaGUgbnVtYmVycyBsYWJlbGVkIG5leHQgdG8gdGhlIGJhcnMgY29ycmVzcG9uZCB0byB0aGUgYXZlcmFnZSBvZiB0aGUgYXZlcmFnZSBkZWF0aCBjb3VudCBwZXIgemlwIGNvZGUuIEZyb20gdGhpcyBwbG90IHdlIG5vdGljZSBhdmVyYWdlIGRlYXRocyBwZXIgemlwIGNvZGUgZHVlIHRvIGluanVyeSBkb3VibGVzIHdoZW4gbW92aW5nIGZyb20gemlwIGNvZGVzIGZyb20gYWdlcyA2MC03MCB0byB6aXAgY29kZXMgd2l0aCBtZWRpYW4gYWdlcyA3MC04MC4gIA0KDQpgYGB7ciwgb3V0LndpZHRoID0gIjEwMDBweCIsIGVjaG89RkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vMDNWaXN1YWxpemF0aW9ucy9TaGlueV9TY3JlZW5zaG90cy9wbG90Ni5wbmciKQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uLzAzVmlzdWFsaXphdGlvbnMvU2hpbnlfU2NyZWVuc2hvdHMvcGxvdDYuMS5wbmciKQ0KYGBgDQoNCkZyb20gdGhlIHJlZmVybmNlIGxpbmUgd2UgY2FuIG5vdGUgdGhhdCB0aGUgY291bnQgb2YgZGVhdGhzIGJ5IHN1aWNpZGUgaGFzIGEgdGVuZGVuY3kgdG8gZ3JvdyBjbG9zZXIgdG8gdGhlIGF2ZXJhZ2UgYXMgbWVkaWFuIGluY29tZSBpbmNyZWFzZXMuDQoNCiMjIyMqKlNoaW55IC0gIERvbWluYW50IFJhY2UgQmFyIENoYXJ0IEZpbmRpbmcqKg0KDQpUaGlzIGltYWdlIHNob3dzIHRoZSBiYXJjaGFydCBjcmVhdGVkIGZyb20gZ3JvdXBpbmcgemlwIGNvZGVzIGJ5IGRvbWluYW50IHJhY2UuDQoNCkZyb20gdGhpcyBiYXJjaGFydCB3ZSBmaW5kIG91dCB0aGF0IG9ubHkgYW1lcmljYW4gaW5kaWFuIGRvbWluYXRlZCB6aXAgY29kZXMgc3VmZmVyZWQgZGVhdGhzIGR1ZSB0byBpbmp1cmllcyBhYm92ZSB0aGUgYXZlcmFnZSBjb3VudCBvZiBkZWF0aHMgZHVlIHRvIGEgY2F1c2UuIEFsbCBvdGhlciByYWNlcyBoYWQgZGVhdGhzIGR1ZSB0byBpbmp1cnkgYmVsb3cgdGhlIGNhdXNlIGRlYXRoIGF2ZXJhZ2UuDQoNCg0KDQojKipLZXkgZm9yIENhdXNlcyBvZiBEZWF0aCBBYmJyZXZpYXRpb25zKioNCkNhdXNlLW9mLWRlYXRoIHdlcmUgY29kZWQgdXNpbmcgdGhlIFRlbnRoIFJldmlzaW9uIG9mIHRoZSBJbnRlcm5hdGlvbmFsIENsYXNzaWZpY2F0aW9uIG9mIERpc2Vhc2VzIGNvZGVzIChJQ0QtMTApLiBUaGlzIGlzIGluIHRoZSBzYW1lIGRhdGEud29ybGQgcHJvZmlsZSAoQGhlYWx0aCkgdGhhdCB3ZSByZXRyaWV2ZWQgb3VyIGRhdGEgZm9yIHRoZSBjb3VudCBvZiBkZWF0aHMgYnkgY2F1c2VzIGZyb20uDQoNCiogSFREIC0gRGlzZWFzZXMgb2YgdGhlIEhlYXJ0DQoqIENBTiAtIE1hbGlnbmFudCBOZW9wbGFzbXMgKENhbmNlcnMpDQoqIFNUSyAtIENlcmVicm92YXNjdWxhciBEaXNlYXNlIChTdHJva2UpDQoqIENMRCAtIENocm9uaWMgTG93ZXIgUmVzcGlyYXRvcnkgRGlzZWFzZSAoQ0xSRCkNCiogSU5KIC0gVW5pbnRlbnRpb25hbCBJbmp1cmllcw0KKiBQTkYgLSBQbmV1bW9uaWEgYW5kIEluZmx1ZW56YQ0KKiBESUEgLSBEaWFiZXRlcyBNZWxsaXR1cw0KKiBBTFogLSBBbHpoZWltZXIncyBEaXNlYXNlDQoqIExJViAtIENocm9uaWMgTGl2ZXIgRGlzZWFzZSBhbmQgQ2lycmhvc2lzDQoqIFNVSSAtIEludGVudGlvbmFsIFNlbGYgSGFybSAoU3VpY2lkZSkNCiogSFlQIC0gRXNzZW50aWFsIEh5cGVydGVuc2lvbiBhbmQgSHlwZXJ0ZW5zaXZlIFJlbmFsIERpc2Vhc2UNCiogSE9NIC0gSG9taWNpZGUNCiogTkVQIC0gTmVwaHJpdGlzLCBOZXBocm90aWMgU3luZHJvbWUgYW5kIE5lcGhyb3Npcw0KKiBPVEggLSBBbGwgT3RoZXIgQ2F1c2VzIG9mIERlYXRoDQoNCiMqKlNRTCBRdWVyeSBmb3IgR3JvdXBpbmcgYW5kIEpvaW5pbmcgZGF0YSoqDQojIyMqKkRvbWluYW50IFJhY2UgUXVlcnkqKg0KDQpUaGUgZm9sbG93aW5nIHF1ZXJ5IGlzIGFuIGV4YW1wbGUgb2YgaG93IHRoZSBjZW5zdXMgZGF0YSB3YXMgcHJvY2Vzc2VkIHRvIGRlZmluZSB0aGUgZG9taW5hbnQgcmFjZSBpbiBhIHppcCBjb2RlLiBUaGUgc2FtZSBwcm9jZXNzIGZvbGxvd2VkIHRvIGRlZmluZSBtZWRpYW4gaW5jb21lIGFuZCBtZWRpYW4gYWdlIGluIGVhY2ggemlwIGNvZGUgYW5hbHl6ZWQuIA0KDQoNCjxjZW50ZXI+IVtjb21tYW5kc10oY29tbWFuZHMucG5nKTwvY2VudGVyPg==